home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / MOR55SRC.ZIP / MORIA / SOURCE / CREATE.C < prev    next >
C/C++ Source or Header  |  1992-12-07  |  13KB  |  560 lines

  1. /* source/create.c: create a player character
  2.  
  3.    Copyright (c) 1989-92 James E. Wilson, Robert A. Koeneke
  4.  
  5.    This software may be copied and distributed for educational, research, and
  6.    not for profit purposes provided that this copyright and statement are
  7.    included in all such copies. */
  8.  
  9. #ifdef __TURBOC__
  10. #include    <stdio.h>
  11. #endif /* __TURBOC__ */
  12.  
  13. #include "config.h"
  14. #include "constant.h"
  15. #include "types.h"
  16. #include "externs.h"
  17.  
  18. #ifdef USG
  19. #ifndef ATARIST_MWC
  20. #include <string.h>
  21. #endif
  22. #else
  23. #include <strings.h>
  24. #endif
  25.  
  26. #if defined(LINT_ARGS)
  27. static void get_stats(void);
  28. static void change_stat(int, int16);
  29. static void get_all_stats(void);
  30. static void choose_race(void);
  31. static void print_history(void);
  32. static void get_history(void);
  33. static void get_sex(void);
  34. static void get_ahw(void);
  35. static void get_class(void);
  36. static int monval(int8u);
  37. static void get_money(void);
  38. #endif
  39.  
  40. /* Generates character's stats                -JWT-    */
  41. static void get_stats()
  42. {
  43.   register int i, tot;
  44.   int dice[18];
  45.  
  46.   do
  47.     {
  48.       tot = 0;
  49.       for (i = 0; i < 18; i++)
  50.     {
  51.       dice[i] = randint (3 + i % 3);  /* Roll 3,4,5 sided dice once each */
  52.       tot += dice[i];
  53.     }
  54.     }
  55.   while (tot <= 42 || tot >= 54);
  56.  
  57.   for (i = 0; i < 6; i++)
  58.     py.stats.max_stat[i] = 5 + dice[3*i] + dice[3*i+1] + dice[3*i+2];
  59. }
  60.  
  61.  
  62. /* Changes stats by given amount                -JWT-    */
  63. static void change_stat(stat, amount)
  64. int stat;
  65. int16 amount;
  66. {
  67.   register int i;
  68.   register int tmp_stat;
  69.  
  70.   tmp_stat = py.stats.max_stat[stat];
  71.   if (amount < 0)
  72.     for (i = 0; i > amount; i--)
  73.       {
  74.     if (tmp_stat > 108)
  75.       tmp_stat--;
  76.     else if (tmp_stat > 88)
  77.       tmp_stat += -randint(6) - 2;
  78.     else if (tmp_stat > 18)
  79.       {
  80.         tmp_stat += -randint(15) - 5;
  81.         if (tmp_stat < 18)
  82.           tmp_stat = 18;
  83.       }
  84.     else if (tmp_stat > 3)
  85.       tmp_stat--;
  86.       }
  87.   else
  88.     for (i = 0; i < amount; i++)
  89.       {
  90.     if (tmp_stat < 18)
  91.       tmp_stat++;
  92.     else if (tmp_stat < 88)
  93.       tmp_stat += randint(15) + 5;
  94.     else if (tmp_stat < 108)
  95.       tmp_stat += randint(6) + 2;
  96.     else if (tmp_stat < 118)
  97.       tmp_stat++;
  98.       }
  99.   py.stats.max_stat[stat] = tmp_stat;
  100. }
  101.  
  102.  
  103. /* generate all stats and modify for race. needed in a separate module so
  104.    looping of character selection would be allowed     -RGM- */
  105. static void get_all_stats ()
  106. {
  107.   register player_type *p_ptr;
  108.   register race_type *r_ptr;
  109.   register int j;
  110.  
  111.   p_ptr = &py;
  112.   r_ptr = &race[p_ptr->misc.prace];
  113.   get_stats ();
  114.   change_stat (A_STR, r_ptr->str_adj);
  115.   change_stat (A_INT, r_ptr->int_adj);
  116.   change_stat (A_WIS, r_ptr->wis_adj);
  117.   change_stat (A_DEX, r_ptr->dex_adj);
  118.   change_stat (A_CON, r_ptr->con_adj);
  119.   change_stat (A_CHR, r_ptr->chr_adj);
  120.   for (j = 0; j < 6; j++)
  121.     {
  122.       py.stats.cur_stat[j] = py.stats.max_stat[j];
  123.       set_use_stat (j);
  124.     }
  125.  
  126.   p_ptr->misc.srh    = r_ptr->srh;
  127.   p_ptr->misc.bth    = r_ptr->bth;
  128.   p_ptr->misc.bthb   = r_ptr->bthb;
  129.   p_ptr->misc.fos    = r_ptr->fos;
  130.   p_ptr->misc.stl    = r_ptr->stl;
  131.   p_ptr->misc.save   = r_ptr->bsav;
  132.   p_ptr->misc.hitdie = r_ptr->bhitdie;
  133.   p_ptr->misc.lev    = 1;
  134.   p_ptr->misc.ptodam = todam_adj();
  135.   p_ptr->misc.ptohit = tohit_adj();
  136.   p_ptr->misc.ptoac  = 0;
  137.   p_ptr->misc.pac    = toac_adj();
  138.   p_ptr->misc.expfact = r_ptr->b_exp;
  139.   p_ptr->flags.see_infra = r_ptr->infra;
  140. }
  141.  
  142.  
  143. /* Allows player to select a race            -JWT-    */
  144. static void choose_race()
  145. {
  146.   register int j, k;
  147.   int l, m, exit_flag;
  148.   char s;
  149.   char tmp_str[80];
  150.   register player_type *p_ptr;
  151.   register race_type *r_ptr;
  152.  
  153.   j = 0;
  154.   k = 0;
  155.   l = 2;
  156.   m = 21;
  157.   clear_from (20);
  158.   put_buffer("Choose a race (? for Help):", 20, 2);
  159.   do
  160.     {
  161.       (void) sprintf(tmp_str, "%c) %s", k+'a', race[j].trace);
  162.       put_buffer(tmp_str, m, l);
  163.       k++;
  164.       l += 15;
  165.       if (l > 70)
  166.     {
  167.       l = 2;
  168.       m++;
  169.     }
  170.       j++;
  171.     }
  172.   while (j < MAX_RACES);
  173.   exit_flag = FALSE;
  174.   do
  175.     {
  176.       move_cursor (20, 30);
  177.       s = inkey();
  178.       j = s - 'a';
  179.       if ((j < MAX_RACES) && (j >= 0))
  180.     exit_flag = TRUE;
  181.       else if (s == '?')
  182.     helpfile (MORIA_WELCOME);
  183.       else
  184.     bell ();
  185.     }
  186.   while (!exit_flag);
  187.  
  188.   p_ptr = &py;
  189.   r_ptr = &race[j];
  190.   p_ptr->misc.prace  = j;
  191.   put_buffer(r_ptr->trace, 3, 15);
  192. }
  193.  
  194.  
  195. /* Will print the history of a character            -JWT-    */
  196. static void print_history()
  197. {
  198.   register int i;
  199.  
  200.   put_buffer("Character Background", 14, 27);
  201.   for (i = 0; i < 4; i++)
  202.     prt(py.misc.history[i], i+15, 10);
  203. }
  204.  
  205.  
  206. /* Get the racial history, determines social class    -RAK-    */
  207. /* Assumptions:    Each race has init history beginning at        */
  208. /*        (race-1)*3+1                    */
  209. /*        All history parts are in ascending order    */
  210. static void get_history()
  211. {
  212.   int hist_ptr, cur_ptr, test_roll, flag;
  213.   register int start_pos, end_pos, cur_len;
  214.   int line_ctr, new_start, social_class;
  215.   char history_block[240];
  216.   register background_type *b_ptr;
  217.  
  218.   /* Get a block of history text                */
  219.   hist_ptr = py.misc.prace*3 + 1;
  220.   history_block[0] = '\0';
  221.   social_class = randint(4);
  222.   cur_ptr = 0;
  223.   do
  224.     {
  225.       flag = FALSE;
  226.       do
  227.     {
  228.       if (background[cur_ptr].chart == hist_ptr)
  229.         {
  230.           test_roll = randint(100);
  231.           while (test_roll > background[cur_ptr].roll)
  232.         cur_ptr++;
  233.           b_ptr = &background[cur_ptr];
  234.           (void) strcat(history_block, b_ptr->info);
  235.           social_class += b_ptr->bonus - 50;
  236.           if (hist_ptr > b_ptr->next)
  237.         cur_ptr = 0;
  238.           hist_ptr = b_ptr->next;
  239.           flag = TRUE;
  240.         }
  241.       else
  242.         cur_ptr++;
  243.     }
  244.       while (!flag);
  245.     }
  246.   while (hist_ptr >= 1);
  247.  
  248.   /* clear the previous history strings */
  249.   for (hist_ptr = 0; hist_ptr < 4; hist_ptr++)
  250.     py.misc.history[hist_ptr][0] = '\0';
  251.  
  252.   /* Process block of history text for pretty output    */
  253.   start_pos = 0;
  254.   end_pos   = strlen(history_block) - 1;
  255.   line_ctr  = 0;
  256.   flag = FALSE;
  257.   while (history_block[end_pos] == ' ')
  258.     end_pos--;
  259.   do
  260.     {
  261.       while (history_block[start_pos] == ' ')
  262.     start_pos++;
  263.       cur_len = end_pos - start_pos + 1;
  264.       if (cur_len > 60)
  265.     {
  266.       cur_len = 60;
  267.       while (history_block[start_pos+cur_len-1] != ' ')
  268.         cur_len--;
  269.       new_start = start_pos + cur_len;
  270.       while (history_block[start_pos+cur_len-1] == ' ')
  271.         cur_len--;
  272.     }
  273.       else
  274.     flag = TRUE;
  275.       (void) strncpy(py.misc.history[line_ctr], &history_block[start_pos],
  276.              cur_len);
  277.       py.misc.history[line_ctr][cur_len] = '\0';
  278.       line_ctr++;
  279.       start_pos = new_start;
  280.     }
  281.   while (!flag);
  282.  
  283.   /* Compute social class for player            */
  284.   if (social_class > 100)
  285.     social_class = 100;
  286.   else if (social_class < 1)
  287.     social_class = 1;
  288.   py.misc.sc = social_class;
  289. }
  290.  
  291.  
  292. /* Gets the character's sex                -JWT-    */
  293. static void get_sex()
  294. {
  295.   register int exit_flag;
  296.   char c;
  297.  
  298.   exit_flag = FALSE;
  299.   clear_from (20);
  300.   put_buffer("Choose a sex (? for Help):", 20, 2);
  301.   put_buffer("m) Male       f) Female", 21, 2);
  302.   do
  303.     {
  304.       move_cursor (20, 29);
  305.       /* speed not important here */
  306.       c = inkey();
  307.       if (c == 'f' || c == 'F')
  308.     {
  309.       py.misc.male = FALSE;
  310.       put_buffer("Female", 4, 15);
  311.       exit_flag = TRUE;
  312.     }
  313.       else if (c == 'm' || c == 'M')
  314.     {
  315.       py.misc.male = TRUE;
  316.       put_buffer("Male", 4, 15);
  317.       exit_flag = TRUE;
  318.     }
  319.       else if (c == '?')
  320.     helpfile (MORIA_WELCOME);
  321.       else
  322.     bell ();
  323.     }
  324.   while (!exit_flag);
  325. }
  326.  
  327.  
  328. /* Computes character's age, height, and weight        -JWT-    */
  329. static void get_ahw()
  330. {
  331.   register int i;
  332.  
  333.   i = py.misc.prace;
  334.   py.misc.age = race[i].b_age + randint((int)race[i].m_age);
  335.   if (py.misc.male)
  336.     {
  337.       py.misc.ht = randnor((int)race[i].m_b_ht, (int)race[i].m_m_ht);
  338.       py.misc.wt = randnor((int)race[i].m_b_wt, (int)race[i].m_m_wt);
  339.     }
  340.   else
  341.     {
  342.       py.misc.ht = randnor((int)race[i].f_b_ht, (int)race[i].f_m_ht);
  343.       py.misc.wt = randnor((int)race[i].f_b_wt, (int)race[i].f_m_wt);
  344.     }
  345.   py.misc.disarm = race[i].b_dis + todis_adj();
  346. }
  347.  
  348.  
  349. /* Gets a character class                -JWT-    */
  350. static void get_class()
  351. {
  352.   register int i, j;
  353.   int k, l, m, min_value, max_value;
  354.   int cl[MAX_CLASS], exit_flag;
  355.   register struct misc *m_ptr;
  356.   register player_type *p_ptr;
  357.   class_type *c_ptr;
  358.   char tmp_str[80], s;
  359.   int32u mask;
  360.  
  361.   for (j = 0; j < MAX_CLASS; j++)
  362.     cl[j] = 0;
  363.   i = py.misc.prace;
  364.   j = 0;
  365.   k = 0;
  366.   l = 2;
  367.   m = 21;
  368.   mask = 0x1;
  369.   clear_from (20);
  370.   put_buffer("Choose a class (? for Help):", 20, 2);
  371.   do
  372.     {
  373.       if (race[i].rtclass & mask)
  374.     {
  375.       (void) sprintf(tmp_str, "%c) %s", k+'a', class[j].title);
  376.       put_buffer(tmp_str, m, l);
  377.       cl[k] = j;
  378.       l += 15;
  379.       if (l > 70)
  380.         {
  381.           l = 2;
  382.           m++;
  383.         }
  384.       k++;
  385.     }
  386.       j++;
  387.       mask <<= 1;
  388.     }
  389.   while (j < MAX_CLASS);
  390.   py.misc.pclass = 0;
  391.   exit_flag = FALSE;
  392.   do
  393.     {
  394.       move_cursor (20, 31);
  395.       s = inkey();
  396.       j = s - 'a';
  397.       if ((j < k) && (j >= 0))
  398.     {
  399.       py.misc.pclass = cl[j];
  400.       c_ptr = &class[py.misc.pclass];
  401.       exit_flag = TRUE;
  402.       clear_from (20);
  403.       put_buffer(c_ptr->title, 5, 15);
  404.  
  405.       /* Adjust the stats for the class adjustment        -RAK-    */
  406.       p_ptr = &py;
  407.       change_stat (A_STR, c_ptr->madj_str);
  408.       change_stat (A_INT, c_ptr->madj_int);
  409.       change_stat (A_WIS, c_ptr->madj_wis);
  410.       change_stat (A_DEX, c_ptr->madj_dex);
  411.       change_stat (A_CON, c_ptr->madj_con);
  412.       change_stat (A_CHR, c_ptr->madj_chr);
  413.       for(i = 0; i < 6; i++)
  414.         {
  415.           p_ptr->stats.cur_stat[i] = p_ptr->stats.max_stat[i];
  416.           set_use_stat(i);
  417.         }
  418.  
  419.       p_ptr->misc.ptodam = todam_adj();    /* Real values        */
  420.       p_ptr->misc.ptohit = tohit_adj();
  421.       p_ptr->misc.ptoac  = toac_adj();
  422.       p_ptr->misc.pac    = 0;
  423.       p_ptr->misc.dis_td = p_ptr->misc.ptodam; /* Displayed values    */
  424.       p_ptr->misc.dis_th = p_ptr->misc.ptohit;
  425.       p_ptr->misc.dis_tac= p_ptr->misc.ptoac;
  426.       p_ptr->misc.dis_ac = p_ptr->misc.pac + p_ptr->misc.dis_tac;
  427.  
  428.       /* now set misc stats, do this after setting stats because
  429.          of con_adj() for hitpoints */
  430.       m_ptr = &py.misc;
  431.       m_ptr->hitdie += c_ptr->adj_hd;
  432.       m_ptr->mhp = con_adj() + m_ptr->hitdie;
  433.       m_ptr->chp = m_ptr->mhp;
  434.       m_ptr->chp_frac = 0;
  435.  
  436.       /* initialize hit_points array */
  437.       /* put bounds on total possible hp, only succeed if it is within
  438.          1/8 of average value */
  439.       min_value = (MAX_PLAYER_LEVEL*3/8 * (m_ptr->hitdie-1)) +
  440.         MAX_PLAYER_LEVEL;
  441.       max_value = (MAX_PLAYER_LEVEL*5/8 * (m_ptr->hitdie-1)) +
  442.         MAX_PLAYER_LEVEL;
  443.       player_hp[0] = m_ptr->hitdie;
  444.       do
  445.         {
  446.           for (i = 1; i < MAX_PLAYER_LEVEL; i++)
  447.         {
  448. #ifdef AMIGA        /* Stupid Aztec C 5.0 bug work around CBG */
  449.           player_hp[i] = player_hp[i-1] + randint ((int)m_ptr->hitdie);
  450. #else
  451.           player_hp[i] = randint((int)m_ptr->hitdie);
  452.           player_hp[i] += player_hp[i-1];
  453. #endif
  454.         }
  455.         }
  456.       while ((player_hp[MAX_PLAYER_LEVEL-1] < min_value) ||
  457.          (player_hp[MAX_PLAYER_LEVEL-1] > max_value));
  458.  
  459.       m_ptr->bth += c_ptr->mbth;
  460.       m_ptr->bthb += c_ptr->mbthb;    /*RAK*/
  461.       m_ptr->srh += c_ptr->msrh;
  462.       m_ptr->disarm += c_ptr->mdis;
  463.       m_ptr->fos += c_ptr->mfos;
  464.       m_ptr->stl += c_ptr->mstl;
  465.       m_ptr->save += c_ptr->msav;
  466.       m_ptr->expfact += c_ptr->m_exp;
  467.     }
  468.       else if (s == '?')
  469.     helpfile (MORIA_WELCOME);
  470.       else
  471.     bell ();
  472.     }
  473.   while (!exit_flag);
  474. }
  475.  
  476.  
  477. /* Given a stat value, return a monetary value, which affects the amount
  478.    of gold a player has. */
  479. static int monval (i)
  480. int8u i;
  481. {
  482.   return 5 * ((int)i - 10);
  483. }
  484.  
  485.  
  486. static void get_money()
  487. {
  488.   register int tmp, gold;
  489.   register int8u *a_ptr;
  490.  
  491.   a_ptr = py.stats.max_stat;
  492.   tmp = monval (a_ptr[A_STR]) + monval (a_ptr[A_INT])
  493.       + monval (a_ptr[A_WIS]) + monval (a_ptr[A_CON])
  494.       + monval (a_ptr[A_DEX]);
  495.  
  496.   gold = py.misc.sc*6 + randint (25) + 325;    /* Social Class adj */
  497.   gold -= tmp;                    /* Stat adj */
  498.   gold += monval (a_ptr[A_CHR]);        /* Charisma adj    */
  499.   if (!py.misc.male)
  500.     gold += 50;            /* She charmed the banker into it! -CJS- */
  501.   if (gold < 80)
  502.     gold = 80;            /* Minimum */
  503.   py.misc.au = gold;
  504. }
  505.  
  506.  
  507. /* ---------- M A I N  for Character Creation Routine ---------- */
  508. /*                            -JWT-    */
  509. void create_character()
  510. {
  511.   register int exit_flag = 1;
  512.   register char c;
  513.  
  514.   put_character();
  515.   choose_race();
  516.   get_sex();
  517.  
  518.   /* here we start a loop giving a player a choice of characters -RGM- */
  519.   get_all_stats ();
  520.   get_history();
  521.   get_ahw();
  522.   print_history();
  523.   put_misc1();
  524.   put_stats();
  525.  
  526.   clear_from (20);
  527.   put_buffer("Hit space to reroll or ESC to accept characteristics: ", 20, 2);
  528.   do
  529.     {
  530.       move_cursor (20, 56);
  531.       c = inkey();
  532.       if (c == ESCAPE)
  533.     exit_flag = 0;
  534.       else if (c == ' ')
  535.     {
  536.       get_all_stats ();
  537.       get_history();
  538.       get_ahw();
  539.       print_history();
  540.       put_misc1();
  541.       put_stats();
  542.     }
  543.       else
  544.     bell ();
  545.     }            /* done with stats generation */
  546.   while (exit_flag == 1);
  547.  
  548.   get_class();
  549.   get_money();
  550.   put_stats();
  551.   put_misc2();
  552.   put_misc3();
  553.   get_name();
  554.  
  555.   /* This delay may be reduced, but is recommended to keep players    */
  556.   /* from continuously rolling up characters, which can be VERY    */
  557.   /* expensive CPU wise.                        */
  558.   pause_exit(23, PLAYER_EXIT_PAUSE);
  559. }
  560.